﻿#pragma once
#include <windows.h>
#include <string>
#include <mutex>
#include <fstream>
#include <vector>
#include <cstdint>
#include <cwchar>
#include <memory>
#include <cwctype>
#include <cmath>
#include <cinttypes>
#include <iomanip>
#include <sstream>
#include <unordered_map>
#include <shlobj.h>
#include "StringUtils.h"


#define DEBUG_MODE      // 取消注释以启用日志功能


#ifdef DEBUG_MODE
/**
 * @brief 可实例化的线程安全日志类，每个实例独立写入不同文件。
 *
 * -------------------------------
 * 用法示例：
 * -------------------------------
 * // 1. 创建日志对象，指定日志文件路径（支持相对或绝对路径）
 * Logger log1(L"IDAHook.log", true, true);
 * Logger log2(L"C:\\Logs\\AnotherLog.txt");
 *
 * // 2. 写入日志（支持C风格格式化，自动类型推断）
 * log1.Log("int=%d, str=%s, ptr=%p", 42, "hello", somePtr);
 * log2.Log(L"宽字符串: %ls, 数字: %d", L"测试", 123);
 *
 * // 3. 十六进制转储
 * std::vector<uint8_t> buffer = {0x12, 0x34, 0x56};
 * log1.Log("Hex: %s", Logger::HexDump(buffer.data(), buffer.size()).c_str());
 *
 * // 4. 控制是否显示字符串编码标记
 * log1.SetShowEncodingTags(false);
 *
 *
 * // 5. 日志对象析构时自动关闭文件并写入结束标记
 *
 * -------------------------------
 * 支持的格式化类型：
 *   %d %u %x %X %o %f %s %ls %c %p 等，自动处理宽/窄字符串和指针类型。
 *
 * 线程安全：
 *   支持多线程并发写日志（同一 Logger 实例）。
 *
 * 注意事项：
 *   - 构造时指定日志文件路径，自动创建和初始化文件。
 *   - 析构时自动关闭文件并写入结束标记。
 *   - 日志文件无自动轮转，需自行管理大小。
 *   - 仅本进程线程安全，不支持多进程并发写同一文件。
 */
class Logger {
public:
    /**
     * @brief 构造函数
     * @param filePath 日志文件路径
     * @param showEncodingTags 是否显示编码标记
     * @param showTimestamp 是否显示时间戳
     */
    explicit Logger(
        const std::wstring& filePath,
        bool showEncodingTags = false,
        bool showTimestamp = false
    );

    /**
     * @brief 析构函数，自动关闭日志文件
     */
    ~Logger();

    /**
     * @brief 设置是否显示编码标记（如[UTF-8]）
     * @param show 是否显示
     */
    void SetShowEncodingTags(bool show);

    /**
    * @brief 设置是否显示时间戳
    * @param show 是否显示
    */
    void SetShowTimestamp(bool show);

    /**
     * @brief 十六进制转储（支持任意数据/字符串/宽字符串）
     * @param data 数据指针
     * @param len 数据长度
     * @param compact 是否紧凑显示（无空格/换行）
     * @return 十六进制字符串
     */
    static std::string HexDump(const void* data, size_t len, bool compact = false);
    static std::string HexDump(const std::string& str, bool compact = false);
    static std::string HexDump(const char* str, bool compact = false);
    static std::string HexDump(const std::wstring& wstr, bool compact = false);
    static std::string HexDump(const wchar_t* wstr, bool compact = false);

    /**
     * @brief 写日志（支持C风格格式化，自动类型推断）
     * @param format 格式字符串（支持%s, %d, %p等）
     * @param args 可变参数
     */
    template <typename... Args>
    void Log(const char* format, Args... args) {
        std::lock_guard<std::mutex> lock(m_logMutex);
        if (!m_logFile || !m_logFile->is_open()) return;

        std::string logLine;
        if (m_showTimestamp) logLine = "[" + GetTimestamp() + "] ";

        const std::string utf8Format = EnsureUTF8(format, true);
        const auto convertedArgs = ProcessArguments(args...);
        const std::string formattedMsg = FormatMessage(utf8Format.c_str(), convertedArgs);

        logLine += formattedMsg + "\n";
        OutputDebugStringA(logLine.c_str());
        *m_logFile << logLine;
        m_logFile->flush();
    }

    /**
     * @brief 写日志（宽字符串格式，支持%s, %d, %p等）
     * @param format 宽字符串格式
     * @param args 可变参数
     */
    template <typename... Args>
    void Log(const wchar_t* format, Args... args) {
        std::lock_guard<std::mutex> lock(m_logMutex);
        if (!m_logFile || !m_logFile->is_open()) return;

        std::string logLine;
        if (m_showTimestamp) logLine = "[" + GetTimestamp() + "] ";

        const std::string utf8Format = StringUtils::WideCharToUTF8(format);
        const auto convertedArgs = ProcessArguments(args...);
        const std::string formattedMsg = FormatMessage(utf8Format.c_str(), convertedArgs);

        logLine += formattedMsg + "\n";
        OutputDebugStringA(logLine.c_str());
        *m_logFile << logLine;
        m_logFile->flush();
    }

private:
    // 参数包装结构体
    struct ArgumentWrapper {
        enum class DataType {
            String,      // 窄字符串
            WideString,  // 宽字符串
            Integer,     // 有符号整数
            Unsigned,    // 无符号整数
            Float,       // 浮点数
            Pointer,     // 普通指针
            FunctionPtr, // 函数指针
            NullPtr      // 空指针
        } type;

        std::string stringValue;   // 窄字符串值
        std::wstring wideValue;    // 宽字符串值
        int64_t intValue = 0;      // 整数值
        uint64_t uintValue = 0;    // 无符号整数值
        double floatValue = 0.0;   // 浮点数值
        void* ptrValue = nullptr;  // 指针值
        std::string encodingTag;   // 编码标记

        // 构造函数重载
        ArgumentWrapper(const char* s);
        ArgumentWrapper(const wchar_t* s);
        ArgumentWrapper(const std::string& s);
        ArgumentWrapper(const std::wstring& ws);
        ArgumentWrapper(signed char v) : type(DataType::Integer), intValue(v) {}
        ArgumentWrapper(short v) : type(DataType::Integer), intValue(v) {}
        ArgumentWrapper(int v) : type(DataType::Integer), intValue(v) {}
        ArgumentWrapper(long v) : type(DataType::Integer), intValue(v) {}
        ArgumentWrapper(long long v) : type(DataType::Integer), intValue(v) {}
        ArgumentWrapper(unsigned char v) : type(DataType::Unsigned), uintValue(v) {}
        ArgumentWrapper(unsigned short v) : type(DataType::Unsigned), uintValue(v) {}
        ArgumentWrapper(unsigned int v) : type(DataType::Unsigned), uintValue(v) {}
        ArgumentWrapper(unsigned long v) : type(DataType::Unsigned), uintValue(v) {}
        ArgumentWrapper(unsigned long long v) : type(DataType::Unsigned), uintValue(v) {}
        ArgumentWrapper(float v) : type(DataType::Float), floatValue(v) {}
        ArgumentWrapper(double v) : type(DataType::Float), floatValue(v) {}
        ArgumentWrapper(void* p) : type(DataType::Pointer), ptrValue(p) {}
        ArgumentWrapper(const void* p) : type(DataType::Pointer), ptrValue(const_cast<void*>(p)) {}
        ArgumentWrapper(std::nullptr_t) : type(DataType::NullPtr), ptrValue(nullptr) {}
        ArgumentWrapper(bool v) : type(DataType::Integer), intValue(v ? 1 : 0) {}
        ArgumentWrapper(char c);
        ArgumentWrapper(wchar_t wc);

        // 函数指针支持
        template<typename T>
        ArgumentWrapper(T* ptr) {
            using BaseType = std::remove_cv_t<std::remove_pointer_t<T>>;
            if constexpr (std::is_function_v<BaseType>) {
                type = DataType::FunctionPtr;
                ptrValue = reinterpret_cast<void*>(ptr);
            }
            else {
                type = DataType::Pointer;
                ptrValue = const_cast<void*>(static_cast<const void*>(ptr));
            }
        }
    };

    // 实例成员
    std::unique_ptr<std::ofstream> m_logFile;
    std::wstring m_logFilePath;
    std::mutex m_logMutex;
    bool m_showEncodingTags;
    bool m_showTimestamp;

    // 辅助方法
    static std::string EnsureUTF8(const char* str, bool skipTag = false);
    static std::string GetWideEncodingTag();
    static std::string GetEncodingTag(const char* str);
    static std::string GetTimestamp();
    static std::string EscapeSpecialCharacters(const std::string& str);
    std::string FormatMessage(const char* format, const std::vector<ArgumentWrapper>& args) const;

    // 格式化方法
    static std::string FormatInteger(int64_t value, int width, bool zeroPad, bool showSign, bool spaceSign);
    static std::string FormatUnsigned(uint64_t value, int width, bool zeroPad);
    static std::string FormatOctal(uint64_t value, int width, bool zeroPad, bool alternateForm);
    static std::string FormatHex(uint64_t value, int width, bool zeroPad, bool alternateForm, bool uppercase);
    static std::string FormatFloat(double value, int precision, int width, bool zeroPad, bool showSign, bool spaceSign);
    static std::string FormatScientific(double value, int precision, int width, bool zeroPad, bool showSign, bool spaceSign, bool uppercase);
    static std::string FormatGeneral(double value, int precision, int width, bool zeroPad, bool showSign, bool spaceSign, bool uppercase);
    static std::string FormatPointer(void* ptr);
    static std::string FormatFunctionPointer(void* funcPtr);
    static std::string FormatChar(char c);
    static std::string FormatWideChar(wchar_t wc);

    // 参数处理
    template <typename... Args>
    std::vector<ArgumentWrapper> ProcessArguments(Args&&... args) const {
        return { ArgumentWrapper(std::forward<Args>(args))... };
    }
};

// 全局日志对象
extern Logger g_Logger;

#else
// 发布模式下的空实现，所有接口无操作
class Logger {
public:
    explicit Logger(
        const std::wstring& filePath,
        bool showEncodingTags = false,
        bool showTimestamp = false
    ) {}

    ~Logger() {}

    void SetShowEncodingTags(bool) {}
	void SetShowTimestamp(bool) {}

    template <typename... Args>
    void Log(const char*, Args...) {}
    template <typename... Args>
    void Log(const wchar_t*, Args...) {}

    static std::string HexDump(const void*, size_t, bool = false) { return ""; }
    static std::string HexDump(const std::string&, bool = false) { return ""; }
    static std::string HexDump(const char*, bool = false) { return ""; }
    static std::string HexDump(const std::wstring&, bool = false) { return ""; }
    static std::string HexDump(const wchar_t*, bool = false) { return ""; }
};

extern Logger g_Logger;
#endif